#ifndef NOSAL_EXEC_INTERNAL_EXECUTABLES_HANDLER_H
#define NOSAL_EXEC_INTERNAL_EXECUTABLES_HANDLER_H

#include "executable.h"
#include "executables_parser.h"
#include "function_group.h"

namespace netaos {
namespace nosal {
namespace exec {
namespace internal {

/// @brief Class ExecutablesHandler for handling the Executables.
class ExecutablesHandler final
{
public:
    /// @brief Constructor.
    ///
    /// @param list_of_function_groups reference to the list of FunctionGroups with states and associated StartupConfigs.
    /// @param executables_parser an ExecutablesParser instance
    /// @param machine_specific_environment_variables the Machine specific Environment variables for all applications.
    ExecutablesHandler(std::map<std::string, FunctionGroup>& list_of_function_groups,
        ExecutablesParser&& executables_parser,
        std::vector<std::string> machine_specific_environment_variables);

    /// @brief Copy constructor deleted.
    ExecutablesHandler(const ExecutablesHandler&) = delete;

    /// @brief Copy assignment operator deleted.
    ExecutablesHandler& operator=(const ExecutablesHandler&) = delete;

    /// @brief Move constructor deleted.
    ExecutablesHandler(ExecutablesHandler&&) = delete;

    /// @brief Move assignment operator deleted.
    ExecutablesHandler& operator=(ExecutablesHandler&&) = delete;

    /// @brief Default destructor.
    ~ExecutablesHandler() = default;

    /// @brief Get the list of Executables.
    ///
    /// @returns reference to the list_of_executables.
    std::vector<Executable>& GetListOfExecutables() noexcept;

    /// @brief Initial parsing of all Execution Manifests.
    /// @returns Empty Result on success or error code.
    netaos::nosal::core::Result<void> ParseExecutionManifests();

    /// @brief Reparsing all Execution Manifests.
    ///
    /// @returns Empty Result indicating success or error code.
    netaos::nosal::core::Result<void> ReparseExecutionManifests();

private:
    /// @brief reference to the list of FunctionGroups with states and associated StartupConfigs managed by EM.
    std::map<std::string, FunctionGroup>& list_of_function_groups_;

    /// @brief the ExecutablesParser instance held by the handler.
    ExecutablesParser executables_parser_;

    /// @brief the list of Machine specific environment variables
    /// @note required for constructing the StartupConfiguration instances.
    std::vector<std::string> machine_specific_environment_variables_;

    /// @brief list of Executables.
    std::vector<Executable> list_of_executables_;

    /// @brief Assigns a StartupConfiguration to FunctionGroup and their states.
    ///
    /// @param startup_configuration Shared pointer to the StartupConfiguration to be assigned.
    /// @param config_in_manifest reference to the config::StartupConfiguration read from the Manifest.
    void AssignStartupConfigurationToFunctionGroup(std::shared_ptr<StartupConfiguration> startup_configuration,
        const config::StartupConfiguration& config_in_manifest);

    /// @brief Check whether any Executable was newly installed on the image.
    ///
    /// @param[in,out] list_of_new_executables the list of newly parsed Executables.
    void CheckForNewInstallations(std::vector<Executable>& list_of_new_executables);

    /// @brief Check whether any Executables were removed by an update.
    ///
    /// @param[in,out] list_of_new_executables the list of Executables found after reparsing.
    /// @returns Empty Result on success, error code otherwise.
    netaos::nosal::core::Result<void> CheckForRemovedExecutables(const std::vector<Executable>& list_of_new_executables);

    /// @brief Check whether Executables were updated.
    ///
    /// @param[in,out] list_of_new_executables the list of Executables found after reparsing.
    /// @returns Empty Result on success, error code otherwise.
    netaos::nosal::core::Result<void> CheckForUpdatedExecutables(std::vector<Executable>& list_of_new_executables);

    /// @brief Extracts the StartupConfigurations from a Manifest, creates them and assigns them to FunctionGroups.
    ///
    /// @param[in,out] executable the Executable to which Execution Manifest and StartupConfigurations belong.
    void ExtractStartupConfigurationsFromManifest(Executable& executable);
};

}  // namespace internal
}  // namespace exec
}  // namespace nosal
}  // namespace netaos

#endif
